use aes::Aes256;
use base64::{engine::general_purpose, Engine as _, alphabet, engine};
use cbc::{Decryptor, Encryptor};
use cbc::cipher::{BlockDecryptMut, BlockEncryptMut, KeyIvInit};
use rand::Rng;
use sha1::{Digest, Sha1};
use tracing::debug;
use crate::error::{AppError, AppResult};

type Aes256CbcEnc = Encryptor<Aes256>;
type Aes256CbcDec = Decryptor<Aes256>;

pub struct WxCrypto {
    token: String,
    encoding_aes_key: Vec<u8>,
    corp_id: String,
}

impl WxCrypto {
    /// 创建新的 WxCrypto 实例
    pub fn new(token: String, encoding_aes_key: String, corp_id: String) -> AppResult<Self> {
        debug!("[WxCrypto] Initializing with token_len={}, aes_key_len={}, corp_id_len={}",
            token.len(), encoding_aes_key.len(), corp_id.len());
        debug!("[WxCrypto] Original AES key: '{}'", encoding_aes_key);
        
        // EncodingAESKey 是43位字符，需要补充一个'='变成44位Base64编码
        let key_with_padding = format!("{}=", encoding_aes_key);
        debug!("[WxCrypto] AES key with padding: '{}', length: {}", key_with_padding, key_with_padding.len());
        
        // 使用支持宽松填充的 Base64 解码器
        // 创建一个自定义的 engine 配置，允许非标准填充
        const INDULGENT: engine::GeneralPurpose = engine::GeneralPurpose::new(
            &alphabet::STANDARD,
            engine::general_purpose::GeneralPurposeConfig::new()
                .with_decode_allow_trailing_bits(true)
                .with_decode_padding_mode(engine::DecodePaddingMode::Indifferent)
        );
        
        let aes_key = INDULGENT
            .decode(key_with_padding.as_bytes())
            .map_err(|e| {
                debug!("[WxCrypto] Failed to decode AES key: {}", e);
                debug!("[WxCrypto] Key bytes: {:?}", key_with_padding.as_bytes());
                AppError::CryptoError(format!("Failed to decode AES key: {}", e))
            })?;
        
        debug!("[WxCrypto] Decoded AES key length: {}", aes_key.len());
        
        // 验证密钥长度必须是32字节（256位）
        if aes_key.len() != 32 {
            return Err(AppError::CryptoError(
                format!("Invalid AES key length: expected 32 bytes, got {}", aes_key.len())
            ));
        }
        
        debug!("[WxCrypto] WxCrypto initialized successfully");

        Ok(Self {
            token,
            encoding_aes_key: aes_key,
            corp_id,
        })
    }

    /// 验证签名
    pub fn verify_signature(&self, signature: &str, timestamp: &str, nonce: &str, msg: &str) -> AppResult<bool> {
        debug!("[WxCrypto] Verifying signature...");
        debug!("[WxCrypto] Input - signature: {}, timestamp: {}, nonce: {}, msg_len: {}",
            signature, timestamp, nonce, msg.len());
        
        let mut params = vec![&self.token, timestamp, nonce, msg];
        params.sort();
        let concatenated = params.join("");
        debug!("[WxCrypto] Concatenated string length: {}", concatenated.len());
        
        let mut hasher = Sha1::new();
        hasher.update(concatenated.as_bytes());
        let result = hasher.finalize();
        let computed_signature = hex::encode(result);
        
        debug!("[WxCrypto] Expected signature: {}", signature);
        debug!("[WxCrypto] Computed signature: {}", computed_signature);
        
        let is_valid = computed_signature == signature;
        debug!("[WxCrypto] Signature valid: {}", is_valid);
        
        Ok(is_valid)
    }

    /// 解密消息
    pub fn decrypt(&self, encrypt_msg: &str) -> AppResult<String> {
        debug!("[WxCrypto] Decrypting message, encrypted_msg_len: {}", encrypt_msg.len());
        
        // Base64 解码
        let cipher_text = general_purpose::STANDARD
            .decode(encrypt_msg.as_bytes())
            .map_err(|e| {
                debug!("[WxCrypto] Base64 decode failed: {}", e);
                AppError::CryptoError(format!("Failed to decode base64: {}", e))
            })?;
        debug!("[WxCrypto] Base64 decoded, cipher_text_len: {}", cipher_text.len());

        // AES 解密（不使用自动去填充，因为企业微信的填充方式特殊）
        let key = &self.encoding_aes_key[0..32];
        let iv = &self.encoding_aes_key[0..16];
        debug!("[WxCrypto] Using key_len: {}, iv_len: {}", key.len(), iv.len());
        
        let decryptor = Aes256CbcDec::new(key.into(), iv.into());
        let mut buffer = cipher_text.clone();
        
        // 使用 NoPadding 模式，手动处理填充
        let decrypted_data = decryptor
            .decrypt_padded_mut::<cbc::cipher::block_padding::NoPadding>(&mut buffer)
            .map_err(|e| {
                debug!("[WxCrypto] AES decrypt failed: {}", e);
                AppError::CryptoError(format!("Failed to decrypt: {}", e))
            })?;
        debug!("[WxCrypto] AES decrypted, data_len: {}", decrypted_data.len());

        // 手动去除 PKCS7 填充
        if decrypted_data.is_empty() {
            return Err(AppError::CryptoError("Decrypted data is empty".to_string()));
        }
        
        let pad_len = decrypted_data[decrypted_data.len() - 1] as usize;
        debug!("[WxCrypto] PKCS7 padding length: {}", pad_len);
        
        // 验证填充长度
        if pad_len == 0 || pad_len > 32 || pad_len > decrypted_data.len() {
            debug!("[WxCrypto] Invalid padding length: {}", pad_len);
            return Err(AppError::CryptoError(format!("Invalid padding length: {}", pad_len)));
        }
        
        // 去除填充后的数据
        let unpadded_len = decrypted_data.len() - pad_len;
        let unpadded_data = &decrypted_data[0..unpadded_len];
        debug!("[WxCrypto] Data after removing padding: len={}", unpadded_data.len());

        // 去除前16字节随机字符串
        if unpadded_data.len() < 20 {
            debug!("[WxCrypto] Unpadded data too short: {}", unpadded_data.len());
            return Err(AppError::CryptoError("Decrypted data too short".to_string()));
        }

        // 读取消息长度 (网络字节序，大端)
        let msg_len = u32::from_be_bytes([
            unpadded_data[16],
            unpadded_data[17],
            unpadded_data[18],
            unpadded_data[19],
        ]) as usize;
        debug!("[WxCrypto] Message length from header: {}", msg_len);

        // 提取消息内容
        let msg_start = 20;
        let msg_end = msg_start + msg_len;
        
        if msg_end > unpadded_data.len() {
            debug!("[WxCrypto] Invalid message length: msg_end={}, data_len={}",
                msg_end, unpadded_data.len());
            return Err(AppError::CryptoError("Invalid message length".to_string()));
        }

        let msg = String::from_utf8(unpadded_data[msg_start..msg_end].to_vec())
            .map_err(|e| {
                debug!("[WxCrypto] UTF-8 decode failed: {}", e);
                AppError::CryptoError(format!("Failed to decode UTF-8: {}", e))
            })?;
        
        debug!("[WxCrypto] Decrypted message: {}", msg);
        Ok(msg)
    }

    /// 加密消息
    pub fn encrypt(&self, msg: &str) -> AppResult<String> {
        debug!("[WxCrypto] Encrypting message, msg_len: {}", msg.len());
        
        // 生成16字节随机字符串
        let mut rng = rand::thread_rng();
        let mut random_bytes = [0u8; 16];
        rng.fill(&mut random_bytes);
        debug!("[WxCrypto] Generated random bytes");

        // 消息长度 (网络字节序)
        let msg_bytes = msg.as_bytes();
        let msg_len = (msg_bytes.len() as u32).to_be_bytes();
        debug!("[WxCrypto] Message length: {}", msg_bytes.len());

        // 构造明文: random(16B) + msg_len(4B) + msg + corp_id
        let mut plain_text = Vec::new();
        plain_text.extend_from_slice(&random_bytes);
        plain_text.extend_from_slice(&msg_len);
        plain_text.extend_from_slice(msg_bytes);
        plain_text.extend_from_slice(self.corp_id.as_bytes());
        debug!("[WxCrypto] Plain text length before padding: {}", plain_text.len());

        // PKCS7 填充
        let block_size = 16;
        let padding_len = block_size - (plain_text.len() % block_size);
        plain_text.extend(vec![padding_len as u8; padding_len]);
        debug!("[WxCrypto] Plain text length after padding: {} (padding: {})",
            plain_text.len(), padding_len);

        // AES 加密
        let key = &self.encoding_aes_key[0..32];
        let iv = &self.encoding_aes_key[0..16];
        
        let encryptor = Aes256CbcEnc::new(key.into(), iv.into());
        let encrypted = encryptor.encrypt_padded_vec_mut::<cbc::cipher::block_padding::NoPadding>(&plain_text);
        debug!("[WxCrypto] Encrypted data length: {}", encrypted.len());

        // Base64 编码
        let encrypted_base64 = general_purpose::STANDARD.encode(&encrypted);
        debug!("[WxCrypto] Base64 encoded length: {}", encrypted_base64.len());

        Ok(encrypted_base64)
    }

    /// 生成签名
    pub fn generate_signature(&self, timestamp: &str, nonce: &str, encrypt: &str) -> String {
        debug!("[WxCrypto] Generating signature for timestamp: {}, nonce: {}, encrypt_len: {}",
            timestamp, nonce, encrypt.len());
        
        let mut params = vec![&self.token, timestamp, nonce, encrypt];
        params.sort();
        let concatenated = params.join("");
        
        let mut hasher = Sha1::new();
        hasher.update(concatenated.as_bytes());
        let result = hasher.finalize();
        let signature = hex::encode(result);
        
        debug!("[WxCrypto] Generated signature: {}", signature);
        signature
    }
}
